監控系統一般會有兩種方式,一種是由外部去輪詢網站是否正常運作,另外一種則是網站自己去回報自己的狀態。那麼實際上應用該使用哪一種呢?答案是都需要。
由外部去輪詢網站的優點是,網站本身僅僅需要提供一個介面就可以,通常是 PING 或是 HTTP PING,外部只要得到回應,就可以知道網站的狀態;缺點則是,外部可能會因為網路的問題而無法連接到網站,但這時網站可能仍然是存活的。
網站自己去回報自己的狀態,好處是能夠得到的主機資訊更多,也可以排除較多的網路問題;缺點則是會要額外設定要回報到哪裡去。
django-health-check 這個套件主要是前者,提供額外的 url / endpoint,讓外部可以利用 HTTP PING 方式來取得主機的狀態。那 django-health-check 可以檢查哪些並提供什麼樣的資訊呢?它可以幫你檢查這些
接下來,就來看看怎麼安裝跟使用吧。
poetry add django-health-check
# settings
INSTALLED_APPS = [
# ...
'health_check', # required
'health_check.db', # stock Django health checkers
'health_check.cache',
'health_check.storage',
'health_check.contrib.celery', # requires celery
'health_check.contrib.psutil', # disk and memory utilization; requires psutil
'health_check.contrib.s3boto3_storage', # requires boto3 and S3BotoStorage backend
'health_check.contrib.rabbitmq', # requires RabbitMQ broker
'health_check.contrib.redis', # required Redis broker
]
settings 的 INSTALLED_APPS 這邊就是看需要檢查什麼,就加入對應的 app。
再來是加 urls
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path('health/', include('health_check.urls')),
]
經過上面的設定以後,外部在檢查網站時,就可以使用 curl -H "Accept: application/json" [http://example.com/health/](http://example.com/health/)
來檢查,或是打開瀏覽器在網址列輸入 http://example.com/health/ 來看輸出頁面了。
這邊我們只講輸出為 JSON 的情況,假設你啟用了 cache, database, s3 的檢查,那麼 HTTP 狀態馬會是 200,輸出結果就會是
{
"CacheBackend": "working",
"DatabaseBackend": "working",
"S3BotoStorageHealthCheck": "working"
}
working 表示正常運作。
那麼當 HTTP 狀態碼為 500,裡面的項目值顯示為 unavailable 時,則表示有狀況。
除了 django-health-check 提供的檢查模組之外,你也可以撰寫自己的檢查模組
# my_app/backends.py
from health_check.backends import BaseHealthCheckBackend
from health_check.exceptions import ServiceUnavailable
class MyHealthCheckBackend(BaseHealthCheckBackend):
#: The status endpoints will respond with a 200 status code
#: even if the check errors.
critical_service = False
def check_status(self):
# The test code goes here.
# You can use `self.add_error` or
# raise a `HealthCheckException`,
# similar to Django's form validation.
try:
# do check
except Exception as e:
self.add_error(ServiceUnavailable("Unknown error"), e)
def identifier(self):
return self.__class__.__name__ # Display name on the endpoint.
檢查模組必須要繼承 BaseHealthCheckBackend ,然後實作 check_status 這個方法,檢查到錯誤時,使用 self.add_error 加入 ServiceUnavailable,也可以直接丟出 HealthCheckException ,讓呼叫 check_status 方法的程式去處理。critical_service 則是表示檢查到錯誤時的處理方式,型態是 boolean,為 True,表示在錯誤時,要回傳 500 Internal server error,為 False,表示依然回傳 200 OK。
撰寫好之後,在自己的 app 裡,註冊這個檢查模組:
# my_app/app.py
from django.apps import AppConfig
from health_check.plugins import plugin_dir
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
from .backends import MyHealthCheckBackend
plugin_dir.register(MyHealthCheckBackend)
這樣就可以囉。
跟 django-health-check 相似的檢查用模組,還有 django-watchman,使用的方法跟 django-health-check 大同小異,只是 django-watchman 還額外提供了 token 機制,在檢查時,可以帶入 token,以避免 health 資訊被有心人利用。
或許後面有機會再來介紹這個套件。
Backend 不只是單純的讓網站或服務能運行就好,還需要考慮到之後的監控跟維護,在監控的情況下,才能夠做出更精細的管理與控制,提昇網站/服務的可靠度。